
// 定义一个函数充当 Promise 的执行器
let executor = function( resolve , reject ){
    // 延迟执行
    setTimeout( function(){
        // 随机产生一个[ 0 , 1 )之间的浮点数
        let x = Math.random();
        console.log( 'random: ' , x );
        if( x > 0.5 ) {
            // 如果要兑现承诺则调用 resolve 函数
            resolve();
        } else {
            // 如果要拒绝承诺则调用 reject 函数
            reject();
        }
    } , 1000 );
}

// 创建一个新的 Promise 实例并在其构造函数中执行 executor 函数
let p = new Promise( executor );
console.log( p );

let onFulfilled = function(){
    console.log('fulfilled');
}

// 当承诺被兑现时就调用 then 函数的参数所传递的函数
// then 执行后返回一个新的 Promise实例
p = p.then( onFulfilled );
console.log( 'then 执行后返回的 Promise 实例: ' , p );

let onRejected = function(){
    console.log('rejected');
}
// 当承诺被拒绝时就调用 catch 函数的参数所传递的函数
// catch 执行后返回一个新的 Promise实例
p = p.catch( onRejected );
console.log( 'catch 执行后返回的 Promise 实例: ' , p );

p = p.finally( () => console.log('finally') );
console.log( 'finally 执行后返回的 Promise 实例: ' , p );

// 总结:
// 1、通过构造方法来创建 Promise 实例
//    let p = new Promise( executor ); // executor 是个函数
//    在 Promise 构造函数内调用 executor 并为其传递两个函数做参数
//    因此在我们定义的 executor 函数内有机会调用由 Promise 构造函数所传递的两个函数
// 2、当承诺被兑现时就调用 then 函数的参数所传递的函数
//    then 是一定会执行的，并且会返回新的 Promise 实例
//    但是 then 的参数对应的函数不一定会执行 (主要看状态如何变化)
// 3、当承诺被拒绝时就调用 catch 函数的参数所传递的函数
//    catch 是一定会执行的，并且会返回新的 Promise 实例
//    但是 catch 的参数对应的函数不一定会执行 (主要看状态如何变化)
// 4、不论承诺被兑现还是被拒绝，fianlly 参数对应的函数都会执行
//    fianlly 函数是一定会执行的，并其会返回新的 Promise 实例